//package crypto;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.*;

public class CryptAnalyzer {
	
	private Vector<Character[][]> potentialPads;
	private Vector<Character[][]> pads;
	private Vector<String> cipherTextList;
	private int messageCount;
	private int numberOfRows = 50;
	private int numberOfColumns = 80;
	
	public CryptAnalyzer(String cipherFilenameList) {
		potentialPads = new Vector<Character[][]>();
		pads = new Vector<Character[][]>();
		cipherTextList = new Vector<String>();
		messageCount = cipherFilenameList.length() - cipherFilenameList.replaceAll("\\,", "").length();
		
		for (String cipherTextFilename : cipherFilenameList.split(",")) {
			try {
				FileReader fr = new FileReader(cipherTextFilename + ".txt");
				String cipherText = new String();
				Character currentCharacter = new Character((char) fr.read());

				while (currentCharacter.charValue() != -1) {
					cipherText += currentCharacter.toString();
					currentCharacter = new Character((char) fr.read());
				}
				cipherTextList.add(cipherText);
				fr.close();
			} catch (Exception e) {
				System.err.println("ERROR: " + e);
			}
		}
	}
	
	public void retrievePads() {
		/* analyze the results of getPotentialPads, output the real pads
        TODO: 
            * call getPotentialPads()
                for first trial, with just one pad, call getSinglePad()
            * call outputPad() for each item returned from getPotentialPads() or
                getSingle Pad()
        */
	}
	
	public String getPotentialPads(int assumedPadCount) {
		String potentialPad = "";
		int[] charCount = new int[127];
		int currentChar;
		for (int i = 1; i <= 4000; i++) {
			if (i % 80 == 0) {
				// the last column of pad is a space
				potentialPad += " ";
				continue;
			}
			for (int j = 1; j <= messageCount; j += assumedPadCount) {
				// if it's not the last column of the 50x80 matrix
				currentChar = (int) cipherTextList.elementAt(j-1).charAt(i-1);
				charCount[currentChar] += 1;
			}
			
			// call getSinglePad, then add the result to potentialPad
			char mostCommonChar = getMostCommonChar(charCount); 
			potentialPad += getSinglePad(mostCommonChar, 'e');
		}

		// for debugging
		assert(potentialPad.length() == 4000);
		
		return potentialPad;
	}
	
	private void outputPad(String outputFilename, String pad) {
		String currentDirectory = System.getProperty("user.dir") + "/";
		try {
			FileWriter fw = new FileWriter(currentDirectory + "/" + outputFilename);
			fw.write(pad);
			fw.close();
		} catch (Exception e) {
			System.err.println("ERROR: " + e);
		}
	}
	
	public String getSinglePad(char cipherChar, char plainText) {
		char pad = 0;
		// guess 1
		pad = (char) (cipherChar - 32 + 64 - plainText);
		if (isPrintableASCII(pad)) {
			return Character.toString(pad);
		}
		// guess 2
		pad = (char) (cipherChar - 32 + 95 + 64 - plainText);
		return Character.toString(pad);
	}

	// helper methods
	private boolean isPrintableASCII(char c) {
		if (c >= 32 && c <= 126) {
			return true;
		}
		return false;
	}
	
	private char getMostCommonChar(int[] charCount) {
		int max = 0;
		int maxIndex = 0;
		
		for (int i = 0; i < charCount.length; i++) {
			if (charCount[i] > max) {
				max = charCount[i];
				maxIndex = i;
			}
		}
		
		return (char) maxIndex;
	}
	
	/*
	 * public static int max(int[] t) {
    int maximum = t[0];   // start with the first value
    for (int i=1; i<t.length; i++) {
        if (t[i] > maximum) {
            maximum = t[i];   // new maximum
        }
    }
    return maximum;
}//end method max

	 * */
}
